use crate::{
    score::RoundResult,
    seat::*,
    table::Table,
    turn::{TurnCard, TurnPlay},
    utils::Utils,
};
use log::info;
use poker_lib::{PokerCard, Suit};
use tge::util::Rand;

#[derive(Debug)]
pub struct Round {
    pub pool: Vec<u8>,
    pub seats: [Seat; 4],
    pub turns: Vec<TurnPlay>,
    // 本盘发牌位置 也就是庄 庄的下家是首个bid_leader
    // round 结束后 banker变为下家
    pub banker: i8,
    // 破黑桃
    pub spades_break: bool,
    pub current_seat_id: usize,
}

// impl Display for Round {
//     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
//         write!(
//             f,
//             "{:?}\n{} {} {} {} {}\n",
//             self.cards,
//             self.counters[0],
//             self.counters[1],
//             self.counters[2],
//             self.counters[3],
//             self.counters[4],
//         );
//         for i in 0..4 {
//             write!(f, "")
//         }

//     }
// }

impl Round {
    pub fn new() -> Self {
        Self {
            pool: vec![],
            seats: [Seat::new(0), Seat::new(1), Seat::new(2), Seat::new(3)],
            turns: vec![],
            spades_break: false,
            banker: -1,
            current_seat_id: 0,
        }
    }

    pub fn reset(&mut self, ctx: &mut Rand) {
        self.pool.clear();
        for i in 0..4 {
            self.seats[i].reset();
        }
        self.turns.clear();
        self.spades_break = false;
        self.select_banker(ctx);
    }

    pub fn next_round(&mut self) {
        self.pool.clear();
        for i in 0..4 {
            self.seats[i].reset();
        }
        self.turns.clear();
        self.spades_break = false;
        self.banker = Utils::get_next_player_id(self.banker as usize) as i8;
    }

    pub fn deal(&mut self, ctx: &mut Rand, joker: bool) {
        self.pool.clear();
        for i in 1..=52u8 {
            if joker {
                if i == 15 {
                    self.pool.push(53);
                    continue;
                } else if i == 28 {
                    self.pool.push(54);
                    continue;
                }
            }
            self.pool.push(i);
        }
        ctx.shuffle(&mut self.pool);
        for i in 0..4 {
            let mut cs: Vec<u16> = vec![];
            for j in 0..13 {
                cs.push(self.pool[i * 13 + j] as u16);
            }
            // cs = vec![2, 7, 9, 16, 17, 18, 22, 23, 25, 31, 34, 37, 53];
            cs.sort();
            self.seats[i].cards.assign(&cs).unwrap();
            self.seats[i].cards_origin.assign(&cs).unwrap();
        }
        self.select_banker(ctx);
        self.prepare_bid();
    }

    pub fn select_banker(&mut self, ctx: &mut Rand) {
        //庄的id, 首个bid 是庄的下家
        //首轮定庄
        if self.banker == -1 {
            self.banker = (ctx.rand() % 4) as i8;
        }
        info!("-------------> select_banker banker {}", self.banker);
    }

    pub fn prepare_bid(&mut self) {
        // 庄家下家开始叫牌
        self.current_seat_id = Utils::get_next_player_id(self.banker as usize);
    }

    // 返回true表示bid状态结束，进入play状态
    pub fn bid(&mut self, bid: i16) -> bool {
        let tid = self.current_seat_id;
        self.seats[tid].bid = Some(bid);
        if self.get_bid_count() == 4 {
            self.prepare_play();
            return true;
        } else {
            //下一个bid
            self.next_seat();
            return false;
        }
    }

    pub fn prepare_play(&mut self) {
        self.next_seat();
        self.turns.clear();
        self.turns.push(TurnPlay::new(self.current_seat_id));
        self.make_cards_can();
    }

    // 返回true表示play状态结束，进入billing状态
    pub fn play(&mut self, out_card: PokerCard) -> bool {
        let tid = self.current_seat_id;
        self.seats[tid].play_card(out_card);
        let turn_out_card = TurnCard {
            seat_id: tid,
            card: out_card,
        };
        // 破黑桃
        if !self.spades_break {
            match out_card.suit {
                Suit::Spade | Suit::Joker => {
                    self.spades_break = true;
                }
                _ => {}
            }
        }
        let turn_cards = &mut self.cur_turn_mut().turn_cards;
        turn_cards.push(turn_out_card);
        let max_seat_id = self.cur_turn().compare_card();
        self.cur_turn_mut().max_seat_id = max_seat_id;
        //计算出牌结果
        let hcount = self.cur_turn().turn_cards.len() as usize;
        if hcount == 4 {
            // 计算本轮墩数
            self.turn_end(self.turns.len() - 1, false);
        }
        if self.get_out_count() == 52 {
            return true;
        } else {
            if hcount != 4 {
                self.next_seat();
            }
            self.make_cards_can();
            return false;
        }
    }

    pub fn cur_turn(&self) -> &TurnPlay {
        let cnt = self.turns.len();
        &self.turns[cnt - 1]
    }

    pub fn cur_turn_mut(&mut self) -> &mut TurnPlay {
        let cnt = self.turns.len();
        &mut self.turns[cnt - 1]
    }

    pub fn bid_leader(&self) -> usize {
        Utils::get_next_player_id(self.banker as usize)
    }

    pub fn cards_out(&self) -> Vec<&TurnCard> {
        let mut cards = vec![];
        for turn in &self.turns {
            for card in &turn.turn_cards {
                cards.push(card);
            }
        }
        cards
    }

    pub fn next_seat(&mut self) {
        self.current_seat_id = Utils::get_next_player_id(self.current_seat_id);
    }

    pub fn make_cards_can(&mut self) {
        let tid = self.current_seat_id;
        self.seats[tid].cards_can.clear();
        let cur_turn = &self.cur_turn();
        let pcs = &self.seats[tid].cards;
        let tcl = cur_turn.turn_cards.len();
        // 首轮，准备好玩家待选牌
        if tcl == 0 || tcl == 4 {
            if pcs[Suit::Heart].n == 0 && pcs[Suit::Club].n == 0 && pcs[Suit::Diamond].n == 0 {
                // 如果手牌只有黑桃, 所有牌都可以出
                self.seats[tid].cards_can.copy_from(pcs);
            } else {
                let mut ccs: Vec<u16> = vec![];
                // 手牌不只有黑桃 或者王牌
                for c in &self.seats[tid].cards.cards {
                    match c.suit {
                        Suit::Spade | Suit::Joker => {
                            if self.spades_break {
                                ccs.push(c.to_u8() as u16);
                            }
                        }
                        _ => {
                            ccs.push(c.to_u8() as u16);
                        }
                    }
                }
                self.seats[tid].cards_can.assign(&ccs).unwrap();
            }
            info!("prepare_play 1st..{:?}", self.seats[tid].cards_can);
        } else {
            // 已经出过首轮牌
            let hfc = cur_turn.turn_cards[0].card.get_suit_num();
            let same_suit_cards = &self.seats[tid]
                .cards
                .get_suit_cards(Suit::from_u8(hfc.0).unwrap());
            if same_suit_cards.len() == 0 {
                // 如果没有首轮花色的牌，所有牌都可以出
                self.seats[tid].cards_can.copy_from(pcs);
            } else {
                // 如果有首轮花色的牌，只可以出这个花色的牌
                self.seats[tid].cards_can.assign(&same_suit_cards).unwrap();
            }
            info!("prepare_play not 1st..{:?}", self.seats[tid].cards_can);
        }
    }

    pub fn get_bid_count(&self) -> usize {
        let mut bid_count = 0usize;
        for i in 0..4 {
            if self.seats[i].bid != None {
                bid_count += 1;
            }
        }
        bid_count
    }

    pub fn get_out_count(&self) -> usize {
        let mut hand_count = 0usize;
        for i in 0..4 {
            hand_count += self.seats[i].cards.len();
        }
        52 - hand_count
    }

    pub fn turn_end(&mut self, tidx: usize, for_ffi_replay: bool) {
        // let cur_turn = &self.turns[self.turns.len() - 1];
        let cur_turn = &self.turns[tidx];
        let max_tid = cur_turn.max_seat_id;
        let turn_cards = &cur_turn.turn_cards;
        let win_card = cur_turn.winning_card().card;
        let leader = &turn_cards[0].card;

        let win_seat = &mut self.seats[max_tid];
        win_seat.tricks += 1;
        // 更新每个玩家的丢牌状态
        for turn_card in turn_cards {
            let seat = &mut self.seats[turn_card.seat_id];
            seat.update_stat_after_turn(&turn_card.card, leader, win_card)
        }
        if !for_ffi_replay {
            //本轮最大的下一个位置出牌 新的turn
            self.turns.push(TurnPlay::new(max_tid));
            self.current_seat_id = max_tid;
        }
        info!("round:{:?}", self);
    }

    pub fn get_player_by_id(&self, player_id: usize) -> &Seat {
        &self.seats[player_id]
    }

    //应该记录一个玩家id 而不是seat_id 预留判断分组用
    pub fn get_team_by_player_id(&self, player_id: usize, mode: i16) -> usize {
        if mode == 1 {
            return if player_id == 0 || player_id == 2 {
                0
            } else {
                1
            };
        } else if mode == 2 {
            return player_id;
        }
        return player_id;
    }

    //team_id 也应该是个唯一id 预留判断分组用
    pub fn get_other_team_by_team_id(&self, team_id: usize) -> usize {
        //单机可以使用这个获取
        // return 1 - team_id;
        if team_id == 0 {
            return 1;
        }
        0
    }
    //获取当前回合 黑桃杀的次数
    pub fn get_spades_break_times(&self) -> u8 {
        let turns = &self.turns;
        let mut break_times = 0;
        for turn in turns {
            if turn.is_spades_break() {
                break_times += 1;
            }
        }
        break_times
    }
    //获取当前回合 每个玩家黑桃杀成功的次数
    pub fn get_player_spades_break_win(&self) -> [u8; 4] {
        let mut groups = [0, 0, 0, 0];
        let turns = &self.turns;
        for turn in turns {
            if let Some(turn_card) = turn.get_spades_break_win_card() {
                groups[turn_card.seat_id] += 1;
            }
        }
        groups
    }
    //获取每个玩家手上最少的花色数量
    pub fn get_player_suit_count(&self) -> [u8; 4] {
        let mut groups = [0, 0, 0, 0];
        let seats = &self.seats;
        for seat in seats {
            groups[seat.id] = seat.cards_origin.get_min_counter_n()
        }
        return groups;
    }
    //获取每个玩家黑桃的数量
    pub fn get_player_spades_count(&self) -> [u8; 4] {
        let mut groups = [0, 0, 0, 0];
        let seats = &self.seats;
        for seat in seats {
            groups[seat.id] = seat.cards_origin.get_trump_count()
        }
        return groups;
    }
    // 队伍是否有叫零
    pub fn is_team_bid_nil(&self, team_id: usize, mode: i16) -> i8 {
        let seats = &self.seats;
        for seat in seats {
            let tid = self.get_team_by_player_id(seat.id, mode);
            if let Some(bid) = seat.bid {
                if bid == 0 && tid == team_id {
                    return seat.id as i8;
                }
            }
        }
        return -1;
    }
    //计算每盘的分数
    pub fn compute_round_result(&self, table: &mut Table) {
        let mut round_result = RoundResult::new();
        let mut team_nil_tricks = [0, 0, 0, 0];
        let seats = &self.seats;
        //计算团队的tricks 和 nil 分数
        for player in seats {
            let player_bid = player.bid.unwrap();
            let player_score = &mut round_result.players[player.id];
            player_score.bid = player_bid as i16;
            player_score.tricks = player.tricks as i16;
            player_score.pile = player.cards_origin.cards.clone();
            let team_id = self.get_team_by_player_id(player.id, table.mode);
            let team_score = &mut round_result.teams[team_id];
            team_score.bid += player_bid as i16;
            if player_bid > 0 {
                team_score.tricks += player.tricks as i16;
                //计算正常叫牌分数
                if player.tricks >= player_bid {
                    let bag = player.tricks - player_bid;
                    player_score.score = bag * table.score_bag + player_bid * table.score_trick;
                    player_score.bags += bag;
                } else {
                    player_score.score = -player_bid * table.score_trick;
                }
            } else {
                //计算 bid nil score
                team_nil_tricks[team_id] += player.tricks;
                let mut num2 = table.score_nil;
                if player.blind_nil {
                    num2 = table.score_blind_nil;
                }
                if player.tricks > 0 {
                    num2 = -num2;
                }
                player_score.bags += player.tricks;
                player_score.nil_bonus = num2;
                player_score.score = num2;
                team_score.round_score += num2;
                team_score.nil_bonus += num2;
                team_score.bid_nil = 1
            }
        }
        //计算得分
        let mut has_bag_penalty = false;
        for team_state in table.team_states.iter_mut() {
            let team_id = team_state.id;
            let team_score = &mut round_result.teams[team_id];
            let tricks = team_score.tricks;
            let bid = team_score.bid;
            if tricks >= bid {
                team_score.bags = tricks - bid;
                team_score.bid_score = team_score.bags * table.score_bag + bid * table.score_trick;
                team_score.round_score += team_score.bid_score;
            } else {
                team_score.bid_score = -bid * table.score_trick;
                team_score.round_score -= bid * table.score_trick;
            }
            team_score.bags += team_nil_tricks[team_id];
            team_state.bags += team_score.bags;
            if team_state.bags >= table.limit_bag {
                team_state.bags -= table.limit_bag;
                team_score.bag_penalty = -table.score_bag_penalty;
                team_score.round_score -= table.score_bag_penalty;
                has_bag_penalty = true;
            }
            team_score.total_bags = team_state.bags;
            team_state.score += team_score.round_score;
            team_score.match_score = team_state.score;
        }
        round_result.round_number = table.rounds.len() as i32 + 1;
        //当前轮是否有破袋子
        round_result.has_bag_penalty = has_bag_penalty;
        //当前轮是否破黑桃
        round_result.spades_broken = if self.spades_break { 1 } else { 0 };
        //计算每个人的黑桃杀 总共的黑桃杀情况
        //当前轮每个玩家的黑桃杀成功次数
        round_result.players_break_win = self.get_player_spades_break_win();
        //获取当前回合 黑桃杀的次数
        round_result.spades_break_times = self.get_spades_break_times();
        //最少花色数
        round_result.players_min_suit = self.get_player_suit_count();
        //每个玩家的主牌数
        round_result.players_spades_suit = self.get_player_spades_count();
        //record every round result winner
        let mut sorted_teams = round_result.teams.clone();
        sorted_teams.sort_by(|a, b| b.round_score.cmp(&a.round_score));
        round_result.win_team_id = sorted_teams[0].id;
        round_result.is_win_bid_nil =
            self.is_team_bid_nil(round_result.win_team_id as usize, table.mode);
        info!("round finish  result -> {:?}", round_result);
        table.rounds.push(round_result);
    }
}
